import "../env";
import { _decorator, Component, Node, Prefab, instantiate, Camera, EditBox } from 'cc';
const { ccclass, property } = _decorator;

import { GateClient } from '../../shared/gateClient/GateClient';
import { GameClient } from "../../shared/gameClient/GameClient";
import { IGameServerInfo } from "../../shared/gateClient/GameServer";
import { ServerListItem } from "../ui/ServerListItem";
import { OTWGameTouchController } from "./OTWGameTouchController";
import { EventHandlers } from "../common/EventHandlers";

declare global {
    let gateServerUrl: string;
}

@ccclass('OTWSceneManager')
export class OTWSceneManager extends Component {

    @property(Prefab)
    ServerInfoListItemTpl?: Prefab;
    @property(Node)
    ServerListWrap?: Node;

    @property(Node)
    ViewLogin?: Node;
    @property(Node)
    ViewServerList?: Node;
    @property(Node)
    ViewGameUI?: Node;
    @property(Node)
    ViewGameLoseUI?: Node;
    @property(Node)
    ViewGameWinUI?: Node;
    @property(Node)
    ViewameAudUI?: Node;
    @property(Node)
    ViewGame3D?: Node;

    @property({ type: Node, tooltip: "存放所有游戏对象的3D节点" })
    public GameObjContainer?: Node;
    @property({ type: Node, tooltip: "存放所有Flag的UI节点" })
    public GameObjFlagUI?: Node;

    @property(Camera)
    public MainCamera?: Camera;

    @property(OTWGameTouchController)
    public TouchCtrl!: OTWGameTouchController;


    @property(EditBox)
    public LoginUserName?: EditBox;

    public gateClient?: GateClient;
    public gameClient?: GameClient;

    public startGameEventHandlers: EventHandlers<() => void> = new EventHandlers<() => void>(this);
    public stopGameEventHandlers: EventHandlers<() => void> = new EventHandlers<() => void>(this);

    private simpleUserName!: string;

    onLoad() {
        this.TouchCtrl.sceneMgr = this;
    }
    async start() {

        var url = typeof (gateServerUrl) === "undefined" ? "http://127.0.0.1:7100/" : gateServerUrl;
        this.gateClient = globalThis.getGateClient(url);
        this.refreshList();

        this.setStep(1);

        //尝试重连之前会话
        var lastReconnectData = getLastReconnectData();
        if (lastReconnectData) {
            this.initGameClient(lastReconnectData.serverUrl);
            this.gameClient!.connectionId = lastReconnectData.reconnectId;
            var ret = await this.gameClient!.reconnect();
            if (!ret.succ) {
                //登录失败, 简单抛个错误
                this.gameClient!.disconnect();
                saveLastReconnectData(null, null);
                return this.gateClient.client.logger?.error("重新连上之前会话失败:" + ret.err);
            }
            saveLastReconnectData(lastReconnectData.serverUrl, this.gameClient!.connectionId);

            this.setStep(3);
            this.startGame();
        }
    }

    
    /**
     * 设置界面流程阶段
     * @date 2022/4/1 - 下午1:34:00
     *
     * @param {number} step 1:登陆界面, 2:选择服务器列表,3游戏中,4游戏失败,5游戏胜利,6观众模式
     */
    public setStep(step: number) {
        if (this.ViewLogin) this.ViewLogin.active = (step == 1);
        if (this.ViewServerList) this.ViewServerList.active = (step == 2);
        if (this.ViewGameUI) this.ViewGameUI.active = (step == 3 || step == 4 || step == 5 || step == 6);
        if (this.ViewGame3D) this.ViewGame3D.active = (step == 3 || step == 4 || step == 5 || step == 6);
        if (this.ViewGameLoseUI) this.ViewGameLoseUI.active = (step == 4);
        if (this.ViewGameWinUI) this.ViewGameWinUI.active = (step == 5);
        if (this.ViewameAudUI) this.ViewameAudUI.active = (step == 6);
    }

    onLogin() {
        this.simpleUserName = this.LoginUserName!.string;
        if (!this.simpleUserName) {
            return;
        }

        this.setStep(2);
    }

    async refreshList() {
        if (!this.ServerInfoListItemTpl || !this.ServerListWrap) return;
        var serverListRet = await this.gateClient!.getGameServers();
        if (!serverListRet.isSucc) {
            this.gateClient!.client.logger?.error("获取游戏服务器列表失败:" + serverListRet.err);
            return;
        }
        this.ServerListWrap.removeAllChildren();
        serverListRet.res.GameServerList.forEach(serverInfo => {
            let itemNode = instantiate(this.ServerInfoListItemTpl!);
            var siComp = itemNode.getComponent(ServerListItem);
            if (siComp) {
                siComp.serverInfo = serverInfo;
                siComp.onClick = (sv) => this.onServerItemClick(sv);
                this.ServerListWrap?.addChild(itemNode);
            }
        });
    }

    async onServerItemClick(sv: IGameServerInfo) {
        if (!this.gateClient) return;

        //从入口服务器获取登录token,这是模拟登录的实现(正常需要输入用户名或密码,或者第三方授权,在入口服务器获得登录token)
        var ret = await this.gateClient.loginByCustomUserName(sv, this.simpleUserName);
        if (!ret.succ) {
            return this.gateClient.client.logger?.error(ret.err);
        }

        var serverUrl = sv.serverWSUrl;
        this.initGameClient(serverUrl);
        var err = await this.gameClient!.login(ret.data!);
        if (err) {
            //登录失败, 简单抛个错误
            return this.gateClient.client.logger?.error(err);
        }
        saveLastReconnectData(serverUrl, this.gameClient!.connectionId);

        this.setStep(3);
        this.startGame();
    }

    initGameClient(serverUrl: string) {
        //登录到游戏服务器
        this.gameClient = globalThis.getGameClient(serverUrl);
        this.gameClient.disconnectHandler = () => {
            return true;
        }
        this.gameClient.onReconnectResult = (succ, err) => {
            if (succ) {
                //成功,则更新connId
                saveLastReconnectData(serverUrl, this.gameClient!.connectionId);
            } else {
                //失败,删除connId,退出游戏
                saveLastReconnectData(null, null);
                this.stopGame();
            }
            return;
        };
    }

    onExitGameClick(event: Event, customEventData: string) {
        this.stopGame(customEventData == 'NoTrigger' ? false : true);
    }

    stopGame(triggerEvent: boolean = false) {
        this.setStep(1);
        saveLastReconnectData(null, null);

        if (triggerEvent) {
            this.stopGameEventHandlers.trigger();
        }
    }

    startGame() {
        this.startGameEventHandlers.trigger();
    }

    showLoseGame() {
        this.setStep(4);
    }
    showWinGame() {
        this.setStep(5);
    }

    update(dt: number) {
    }
    lateUpdate() {
    }
}